from PyQt4.QtGui import QWidget,QVBoxLayout,QMainWindow,QMenu,QSizePolicy
from PyQt4 import QtCore,QtGui
from PyQt4.QtCore import QPointF,QSizeF,QObject,QRectF,QPoint
from KCharts.ui_KChartsWidget import Ui_KChartsWidget
from KUI.KSmartSearch.ui_KChartCompleteDlg import Ui_KChartCompleteDlg
from KCharts.KSingleChartWidget import *
from KModel.KSingleStock import KSingleStock
import pyqtgraph as pg
from pyqtgraph.dockarea import *
import numpy as np
from KCharts import KIndicatorTreeWidget
class KChartsWidget(QWidget):
	''' 
	1] Core Widget to display stock prices by making use of GraphicsLayoutWidget (which is a QGraphicsView behind scene)
	it is responsible to manage all KSingleChartPlots in the same chart(a KSingleChartPlot corresponds to a pyqt plotitem, it intends to show one aspect information of a stock)
	2] each KChart hold :
	one KSingleStock Object: provides data to all display inside this KChart;
	multiple KSingleChartPlot
	one slide bar to control the window of stock data
	'''
	def __init__(self, parent=None):
		super(KChartsWidget, self).__init__(parent)
		self.ui =  Ui_KChartsWidget()
		self.ui.setupUi(self) 
		
		# add Tree Widget
		self.mLayout=QVBoxLayout(self.ui.LeftContainer)
		self.treewdgt=KIndicatorTreeWidget.KIndicatorTreeWidget(self.ui.LeftContainer)
		self.mLayout.setContentsMargins(0,0,0,0) # set blank space between outside of layout and its parent widget		
		self.mLayout.setSpacing(0)
		self.mLayout.addWidget(self.treewdgt)
		
		# set size between of left and right layout
		sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
		sizePolicy.setHorizontalStretch(1) # ratio is 1
		sizePolicy.setVerticalStretch(0)
		self.ui.LeftContainer.setSizePolicy(sizePolicy)
		self.ui.LeftContainer.setMinimumWidth(100)
		
		sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
		sizePolicy.setHorizontalStretch(5) # ratio is 5
		sizePolicy.setVerticalStretch(0)
		self.ui.RightContainer.setSizePolicy(sizePolicy)
		
		
		#Setup Signal
		self.treewdgt.IndicatorChanged.connect(self.OnIndicatorChanged)
		
		#Create Dock Area
		self.dockarea = DockArea()
	

		#Setup Layout
		self.mLayout=QVBoxLayout(self.ui.ChartContainer)
		self.mLayout.setContentsMargins(0,0,0,0) # set blank space between outside of layout and its parent widget		
		self.mLayout.setSpacing(0)
		#self.mLayout.addWidget(self.dockarea)
		
		#Setup Scroll Bars
		self.ui.BarTimeRange.valueChanged.connect(self.ChangeBarTimeRange)	
		self.ui.BtnTimeScale.valueChanged.connect(self.ChangeBarTimeScale)
		self.ui.BtnBarCount.valueChanged.connect(self.ChangeBarCount)
		
		self.allcharts=[] # maitain all KSingleChartPlots in this chart
		self.m_stock=KSingleStock() # create its stock object
		self.m_stock.SetTick('us','nasdaq','aapl')	
		

		self.InitializeScaleAndWindowBar()
		self.UpdateDisplay()	
		
		#have one singlechart by default
		self.AddChart()


		
	def OnIndicatorChanged(self,paradict):

		[ mchart.UpdateIndicator(paradict) for mchart in self.allcharts] # notify all chart to update this indicator
		
	def AddChart(self):
		
		layoutmethod=['left','right']
		for x in range(0,1):
			#mdock = Dock("Price", size=(1, 1))    
			#self.dockarea.addDock(mdock,layoutmethod[x])
			singlechart=KSingleChartWidget(self,self.m_stock)
			#singlechart=QWidget()
			#mdock.addWidget(singlechart)
			
			#self.mLayout.addWidget(singlechart)	
			self.mLayout.addWidget(singlechart)
			self.allcharts.append(singlechart)
			self.treewdgt.ReSendAllCheckedItem() # resend so new chart can know current selection	


			
	def OnSymbolChanged(self, text):
		# triggered when current symbol is changed, could be triggered by KChartsWidget
		(tick,market,country)=str(text).split('.')
		self.m_stock.SetTick(country,market,tick)	

		self.InitializeScaleAndWindowBar() # reset the scale range		
		self.UpdateTimeRangeBar() # reset the time range 
		self.UpdateDisplay()
		
	def UpdateDisplay(self):		
		# Update the display of all KSingleChartWidget, should be called whenever m_stock get updated.				
		for each_plotchart in self.allcharts:
			each_plotchart.UpdateDisplay()	

	def OnContextMenuClicked(self,sAction):
		## execute the command from Context Menu
		(command,para)=sAction.split("_",2)
		if command=="Time":
			self.ChangePeriod(para)
						
	def ChangePeriod(self, period):	
		
		if self.m_stock.ChangePeriod(period)==True: # may return false if period is not allowed		
			self.SetTimeScaleBarValue(period)
			self.UpdateTimeRangeBar() # reset the time range 
			self.UpdateDisplay() #redraw
		
	def SetTimeScaleBarValue(self,value):
		self.ui.BtnTimeScale.setValue(int(value))
		
	def UpdateTimeRangeBar(self):
		# This need to be called whenever stock symbol change or symbol period change.
		m_stock=self.m_stock
		slidebar=self.ui.BarTimeRange
		# setup slide bar to control range
		slidebar.setSingleStep(1)
		slidebar.setPageStep(m_stock.GetWindowLength())
		slidebar.setRange(0,m_stock.GetTotalLength()-m_stock.GetWindowLength())
		slidebar.setValue(m_stock.GetTotalLength()-m_stock.GetWindowLength())	
	
		
	def InitializeScaleAndWindowBar(self):
		# This only need to be called when the stock symbol is changed. 
		m_stock=self.m_stock
		
		# set up scale range bar
		srange=m_stock.GetAllowedPeriodLength()
		slidebar=self.ui.BtnTimeScale
		PageStep=10
		slidebar.setSingleStep(1)
		slidebar.setPageStep(PageStep)
		slidebar.setRange(srange[0],srange[1])
		slidebar.setValue(srange[0])
		
		# set up window length bar
		srange=m_stock.GetAllowedWindowLength()
		slidebar=self.ui.BtnBarCount
		PageStep=50
		slidebar.setSingleStep(10)
		slidebar.setPageStep(PageStep)
		slidebar.setRange(srange[0],srange[1])
		slidebar.setValue(srange[0])		
		
	def ChangeBarTimeRange(self,value):
		# Handle range of scroll bar
		self.m_stock.SetCursorPostion(value)
		self.UpdateDisplay()
		
	def ChangeBarCount(self,value):
		# Handle count of bar in a window
		self.m_stock.SetWindowLength(value)
		self.UpdateTimeRangeBar()
		self.UpdateDisplay()
		
	def ChangeBarTimeScale(self,value):
		# Handle scale of scroll bar
		self.m_stock.ChangePeriod(round(value))
		self.UpdateTimeRangeBar()
		self.UpdateDisplay()
